package com.ruoyi.project.erp.domain;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.ruoyi.common.exception.ServiceException; // 建议使用自定义异常
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.project.erp.mapper.ProjectMapper;
import com.ruoyi.project.erp.mapper.ProjectUserMapper;
import com.ruoyi.project.erp.vo.ProjectExcelVo;
import com.ruoyi.project.system.domain.SysDept;
import com.ruoyi.project.system.domain.SysUser;
import com.ruoyi.project.system.service.ISysDeptService;
import com.ruoyi.project.system.service.ISysUserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 项目数据导入监听器
 *
 * 实现了对Excel数据的逐行处理，包括数据校验、转换、组装和入库。
 * 每一行数据作为一个独立的处理单元，部分行的失败不影响其他行的导入。
 */
public class ProjectDataListener extends AnalysisEventListener<ProjectExcelVo> {
    // ... 其他属性和构造函数保持不变 ...

    private static final Logger log = LoggerFactory.getLogger(ProjectDataListener.class);

    private final ProjectMapper projectMapper;
    private final ProjectUserMapper projectUserMapper;
    private final ISysUserService userService;
    private final ISysDeptService deptService;
    private final boolean isUpdateSupport;
    private final String operName;
    private int successCount = 0;
    private int failureCount = 0;
    private final StringBuilder successMsg = new StringBuilder();
    private final StringBuilder failureMsg = new StringBuilder();

    public ProjectDataListener(ProjectMapper projectMapper, ProjectUserMapper projectUserMapper,
                               ISysUserService userService, ISysDeptService deptService,
                               boolean isUpdateSupport, String operName) {
        this.projectMapper = projectMapper;
        this.projectUserMapper = projectUserMapper;
        this.userService = userService;
        this.deptService = deptService;
        this.isUpdateSupport = isUpdateSupport;
        this.operName = operName;
    }

    /**
     * 【重点修改】每一条数据解析都会来调用
     */
    @Override
    public void invoke(ProjectExcelVo data, AnalysisContext context) {
        int rowIndex = context.readRowHolder().getRowIndex() + 1;
        log.info("开始解析第 {} 行数据: {}", rowIndex, data);

        try {
            // ========== 1. 数据校验 ==========
            if (StringUtils.isBlank(data.getProjectId())) throw new ServiceException("项目编号不能为空");
            if (StringUtils.isBlank(data.getProjectName())) throw new ServiceException("项目名称不能为空");
            if (StringUtils.isBlank(data.getProjectLeaderName())) throw new ServiceException("负责人不能为空");

            // ========== 2. 数据转换与业务校验 ==========

            // --- 处理负责人 ---
            String leaderNickName = data.getProjectLeaderName().trim();
            SysUser queryUser = new SysUser();
            queryUser.setNickName(leaderNickName);
            List<SysUser> leaders = userService.selectUserList(queryUser);
            leaders = leaders.stream().filter(u -> u.getNickName().equals(leaderNickName)).collect(Collectors.toList());

            if (leaders.isEmpty()) {
                throw new ServiceException("负责人 '" + leaderNickName + "' 在系统中不存在");
            }
            if (leaders.size() > 1) {
                throw new ServiceException("负责人姓名 '" + leaderNickName + "' 存在重名用户，无法自动匹配");
            }
            SysUser leader = leaders.get(0);
            if (StringUtils.isBlank(leader.getDdUserId())) {
                throw new ServiceException("负责人 '" + leaderNickName + "' 未关联钉钉用户ID(dd_user_id)，无法导入");
            }

            // --- 处理部门 ---
            Long determinedDeptId;
            String deptName = data.getDeptName() != null ? data.getDeptName().trim() : null;
            if (StringUtils.isNotBlank(deptName)) {
                SysDept dept = deptService.selectDeptByName(deptName);
                if (dept == null) {
                    throw new ServiceException("指定的部门 '" + deptName + "' 不存在，请检查名称是否完全匹配");
                }
                determinedDeptId = dept.getDeptId();
            } else {
                if (leader.getDeptId() == null || leader.getDeptId() == 0L) {
                    throw new ServiceException("负责人 '" + leader.getNickName() + "' 没有关联任何部门，且Excel中部门列为空，无法自动确定部门");
                }
                determinedDeptId = leader.getDeptId();
                log.info("第 {} 行数据部门为空，自动使用负责人所在部门，DeptId: {}", rowIndex, determinedDeptId);
            }

            // ========== 3. 组装主表实体 `Project` ==========
            Project project = new Project();
            project.setProjectId(data.getProjectId().trim());
            project.setProjectName(data.getProjectName().trim());
            project.setProjectGroup(data.getProjectGroup());
            project.setCustomer(data.getCustomer());
            project.setProjectLeader(leader.getDdUserId());
            project.setDeptId(determinedDeptId);
            project.setProjectStartTime(data.getProjectStartTime());
            project.setProjectEndTime(data.getProjectEndTime());
            project.setRemark(data.getRemark());
            project.setUpdateBy(operName);
            project.setUpdateTime(new Date());
            project.setSaleId(leader.getDdUserId());
            // --- 处理项目状态 (文本 -> 编码) ---
            if (StringUtils.isNotBlank(data.getProjectStatusStr())) {
                String statusStr = data.getProjectStatusStr().trim();
                switch (statusStr) {
                    case "进行中": project.setProjectStatus("1"); break;
                    case "已完结": project.setProjectStatus("3"); break;
                    default:
                        throw new ServiceException("无法识别的项目状态: '" + statusStr + "'，目前只接受 '进行中' 或 '已完结'");
                }
            } else {
                project.setProjectStatus("1"); // 如果Excel为空，默认为“进行中”
            }

            // ========== 4. 【修改】组装子表实体 `ProjectUser` ==========
            // 使用 Map 来存储项目成员，key 为 ddUserId，用于自动去重
            Map<String, ProjectUser> projectUserMap = new LinkedHashMap<>();

            // **【新增】首先添加负责人，并设置角色为 '2'**
            // 这里的 leader 对象已经在前面校验过，是有效且唯一的
            projectUserMap.put(leader.getDdUserId(), createProjectUser(project.getProjectId(), leader.getDdUserId(), "2"));

            // --- 处理参与人 ---
            String participantsStr = data.getParticipants();
            if (StringUtils.isNotEmpty(participantsStr)) {
                if ("全部".equals(participantsStr.trim())) {
                    List<SysUser> allUsers = userService.selectUserList(new SysUser());
                    for (SysUser user : allUsers) {
                        if (StringUtils.isNotEmpty(user.getDdUserId()) && "0".equals(user.getStatus())) {
                            // **【修改】使用 putIfAbsent，如果用户（比如负责人）已存在，则不会覆盖，保证了负责人角色为 '2'**
                            projectUserMap.putIfAbsent(user.getDdUserId(), createProjectUser(project.getProjectId(), user.getDdUserId(), "0"));
                        }
                    }
                } else {
                    String[] participantNickNames = participantsStr.split("[,，]");
                    for (String nickName : participantNickNames) {
                        String trimmedNickName = nickName.trim();
                        if (StringUtils.isBlank(trimmedNickName)) continue;

                        SysUser queryParticipant = new SysUser();
                        queryParticipant.setNickName(trimmedNickName);
                        List<SysUser> users = userService.selectUserList(queryParticipant).stream()
                                .filter(u -> u.getNickName().equals(trimmedNickName))
                                .collect(Collectors.toList());

                        if (users.isEmpty()) {
                            log.warn("第 {} 行，参与人 '{}' 在系统中不存在，已跳过。", rowIndex, trimmedNickName);
                            continue;
                        }
                        if (users.size() > 1) {
                            throw new ServiceException("参与人姓名 '" + trimmedNickName + "' 存在重名用户，无法处理");
                        }
                        SysUser participant = users.get(0);
                        if (StringUtils.isBlank(participant.getDdUserId())) {
                            log.warn("第 {} 行，参与人 '{}' 未关联钉钉ID，已跳过。", rowIndex, trimmedNickName);
                            continue;
                        }
                        // **【修改】使用 putIfAbsent 添加参与人，角色为 '0'**
                        projectUserMap.putIfAbsent(participant.getDdUserId(), createProjectUser(project.getProjectId(), participant.getDdUserId(), "0"));
                    }
                }
            }

            // **【新增】将 Map 转换为 List，用于批量插入**
            List<ProjectUser> projectUserList = new ArrayList<>(projectUserMap.values());

            // ========== 5. 数据持久化 ==========
            Project existProject = projectMapper.selectProjectInfoByProjectId(project.getProjectId());

            if (existProject == null) {
                // 新增逻辑
                project.setCreateBy(operName);
                project.setCreateTime(new Date());
                projectMapper.insertProject(project);
                if (!projectUserList.isEmpty()) {
                    projectUserMapper.batchInsertProjectUser(projectUserList);
                }
                successCount++;
                log.info("第 {} 行，项目编号 {} 新增成功。", rowIndex, project.getProjectId());

            } else if (isUpdateSupport) {
                // 更新逻辑
                project.setId(existProject.getId());
                projectMapper.updateProject(project);
                projectUserMapper.deleteProjectUserByProjectId(project.getProjectId());
                if (!projectUserList.isEmpty()) {
                    projectUserMapper.batchInsertProjectUser(projectUserList);
                }
                successCount++;
                log.info("第 {} 行，项目编号 {} 更新成功。", rowIndex, project.getProjectId());

            } else {
                throw new ServiceException("项目编号已存在，且未开启更新支持");
            }

        } catch (Exception e) {
            failureCount++;
            String errorMsg = e.getMessage();
            failureMsg.append("<br/>第 ").append(rowIndex).append(" 行导入失败：").append(errorMsg);
            log.error("第 {} 行数据导入失败: {}", rowIndex, errorMsg, e);
        }
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        log.info("所有数据解析完成！成功: {}, 失败: {}", successCount, failureCount);
    }

    public String getSummary() {
        if (failureCount > 0) {
            failureMsg.insert(0, "很抱歉，导入失败！共 " + successCount + " 条数据成功，" + failureCount + " 条数据格式不正确，错误如下：");
            return failureMsg.toString();
        } else {
            successMsg.insert(0, "恭喜您，数据已全部导入成功！共 " + successCount + " 条。");
            return successMsg.toString();
        }
    }

    /**
     * 【重点修改】创建 ProjectUser 对象的辅助方法，增加了 role 参数
     */
    private ProjectUser createProjectUser(String projectId, String ddUserId, String role) {
        ProjectUser pu = new ProjectUser();
        pu.setProjectId(projectId);
        pu.setDdUserId(ddUserId);
        pu.setRole(role); // **【新增】设置角色**
        pu.setCreateBy(operName);
        pu.setCreateTime(new Date());
        pu.setStatus("1"); // 状态: 1-正常
        return pu;
    }
}